package table_Mixage;

import java.util.ArrayList;

/**
 *  Canal
 *  
 *  Description:  definition d'un canal
 *	
 *	Contenu:
 *		- tableau d'echantillons (valeurs int)
 *		- opération sur les echantillons 		
 *		- opération sur les Fragments
 *
 * @author  François Miller/ Peloux Arnaud</a>
 * @version 1.0
 */

public class Canal{

    private int[] echantillons;
    private int nbech, nbFragment;
    private int dataout, frequence;
    private ArrayList<Fragment> fragments= new ArrayList<Fragment>();
  //----------------------------------------Guetteurs/Setteurs----------------------------------------
    protected int getEchantillon(){
		int res = 0;

		if (dataout < nbech){
		    res = echantillons[dataout];
		    dataout ++;
			}

		return res;

	  }
    protected int getEchantillon(int cur){
		if (cur < nbech){
		    return echantillons[cur];
		}
		return 0;

	  }
    public int getNbech(){return nbech;}
    public void setFrequence(int frq){
    	/**float coef = (float) frequence/(float)frq; 	// >1 si frq est plus grande que frequence perte qualité
		// <1 si frq est plus petite que frequence retenir la valeur plus longtemps
		// =1si frequence est égale à frequence
    	int[] tabtemp= new int[(int)(echantillons.length*coef)];
    	int i=0, j=0;
    	if(coef >1){
    		for(; i<tabtemp.length & j< echantillons.length;i++){
    			if (i%coef < 1)
    				tabtemp[i]=echantillons[j];
    			j++;
    		}

    	}else if(coef<1){

    		for(; i<tabtemp.length & j< echantillons.length;i++){
    			if (i%coef < 0)
    				tabtemp[i]=tabtemp[i-1];
    			else 
    				tabtemp[i]=echantillons[j];
    			j++;
    		}

    	}else if(coef == 1){
    		for(; i<tabtemp.length ;i++){
    			tabtemp[i]=echantillons[i];	
    		}
    	}
    	echantillons=tabtemp.clone();
    	nbech=echantillons.length;
    	*/
    	
    	
    	this.frequence = frq;
    }
    
    public Fragment getFragment(int numeroFragment ){
    	return fragments.get(numeroFragment);
    }
    public int getNbFragment(){return nbFragment;}
    
  //----------------------------------------Constructeurs----------------------------------------
    
    public  Canal(){
    	echantillons = new int[100000];
     }
    public 	Canal(long size,int frequence){
		echantillons = new int[(int)size];
		this.frequence = frequence;
    }
    
    //---------------------------------------- initialisation + Ajout échantillons----------------------------------------

    protected void clear(){
	nbech = 0;
    }
    protected void addEchantillon(int ech){
    	
	if (nbech < echantillons.length){
	    echantillons[nbech] = ech;

	    nbech ++;
		}
    }
    protected void initLecture(){
    	dataout = 0;
    }
    protected void initLecture(int deb){
    	dataout = deb;
    }
    
    public int createFragment(long dateDebut, long duree){
    	refresh();
    	if (dateDebut >= echantillons.length)return 0;
    	if (fragments.add(new Fragment(dateDebut,duree))){
    		 nbFragment ++;
    		 refresh();
    		 return nbFragment-1;
    	 }else return 0;
    }
    
    public void controlVolume(double val){
    	for (int i = 0; i<echantillons.length;i++){
    		echantillons[i]= (int)(echantillons[i]*val);
    	}
    }
 
    public void synchronizeFrequence(int frq){
    	
    	// synchronise le canal avec la frequence passée en parametre
    	double coef= ((double)(frequence))/((double)(frq));
    	int[]  tab= new int[(int)(echantillons.length/ coef)];
    	if (coef < 1){
    		//si frequence supérieur à un ( fréquence locale plus importante)
    		// on tiens la valeur un peut plus.
    		for (int i=0, j=0;i<tab.length;i++){
    			if (i%coef !=0 | i==0){
    				tab[i]= echantillons[j];
    				j=j++;
    			}else
    				tab[i]=tab[i-1];
    		}
    		echantillons= tab.clone();
    	}else if (coef > 1 ){
    		
    		//si frequence inferieur à un ( fréquence locale moins importante)
    		//(on perds de la precision)
    		for (int i=0, j=0;i<echantillons.length;i++){
    			if(i%coef == 0){
    				tab[j]= echantillons[i];

    				j++;
    				
    			}			
    		}
    		
    		
    	}else if (coef == 1){}
    	
    	echantillons= tab.clone();
    	frequence = frq;
    	nbech=echantillons.length;

    }
    
    //---------------------------------------- Opération sur les Fragments----------------------------------------
    
     public void refresh(){
    	for (int i=0; i< nbFragment;){
    		
    		if ((fragments.get(i).getDateDebut()> echantillons.length) | (fragments.get(i).getDuree()==0 )){
    			removeFragment(i);
	
    		}else if(fragments.get(i).getDateFin()>echantillons.length){
    			fragments.get(i).setDateFin(echantillons.length);
    			fragments.get(i).setDuree(fragments.get(i).getDateFin()-fragments.get(i).getDateDebut());
    			
    			i++;

    		}else 
  
    			i++;
    	if(i==nbFragment){
    		nbech= echantillons.length;
    		return;}
    	}
    	nbech= echantillons.length;
    }
    

    public void removeFragment (int numeroFragment){
    	fragments.remove(numeroFragment);
    	nbFragment--;
    	refresh();
    }
    
 

    public void addFragment(int[] echantToAdd,long dateDebut, int frq){
    	float coef = (float) frequence/(float)frq; 	// >1 si frq est plus grande que frequence perte qualité
													// <1 si frq est plus petite que frequence retenir la valeur plus longtemps
													// =1si frequence est égale à frequence
    	int[] tabtemp= new int[(int)(echantToAdd.length*coef)];
    	
    	int i=0, j=0;
    	if(coef >1){
    		for(; i<tabtemp.length & j< echantToAdd.length;i++){
    			if (i%coef < 1)
    				tabtemp[i]=echantToAdd[j];
    			j++;
    		}
    		
    	}else if(coef<1){
    		for(; i<tabtemp.length & j< echantToAdd.length;i++){
    			if (i%coef < 0)
    				tabtemp[i]=tabtemp[i-1];
    			else 
    				tabtemp[i]=echantToAdd[j];
    			j++;
    		}
    		
    	}else if(coef == 1){
    		for(; i<tabtemp.length ;i++){
    				tabtemp[i]=echantToAdd[i];	
    		}
    	}
    	echantToAdd=tabtemp.clone();
    	
    	
    	int[] temp = new int[echantillons.length + echantToAdd.length];
    	int i2=0,j2=0;	

    	for (; i2< dateDebut; i2++){
    		temp[i2] = echantillons[i2];}
    	
    	for ( ; j2< echantToAdd.length;j2++ )
    		temp[i2+j2] = echantToAdd[j2];
    	
    	for ( ;i2< echantillons.length; i2++)
    		temp[i2+j2]=echantillons[i2];
    		
    	echantillons = temp.clone();
    	nbech=echantillons.length;
    	
    }  
    public void deleteFragment(int numFragment){
    	long deb = getFragment(numFragment).getDateDebut();
    	long fin = getFragment(numFragment).getDateFin();
    	long duree = getFragment(numFragment).getDuree();
    	int[] temp = echantillons.clone();
    	long i =0;
    	int j =0;
    	echantillons = new int[(int)(temp.length-duree)];

    	//remplissage du tableau d'echantillons
    	
    	for(;i<deb;i++){
    		echantillons[j] = temp[j];
    		j++;
    	}
    	
    	for(i= (int)fin; i<temp.length;i++){
    			echantillons[j]=temp[(int)i];
    			j++;
    	}
    	removeFragment(numFragment);
    	refresh();
    }
    
    
    public int[] copier(int numFragment){
    	refresh();
    	
    	long deb	= getFragment(numFragment).getDateDebut();
    	long fin 	= getFragment(numFragment).getDateFin();
    	long duree	= getFragment(numFragment).getDuree();
    	int [] temp = new int[(int) duree];
    	for (long i=deb ; i< fin;i++){
    		temp[(int)(i-deb)]=echantillons[(int)i];
    	}
    	return temp;
    }  
    public void coller(int[]tab, long debut, int frq){ 
    	// on remplace une partie du tableau par le fragment
    	
    	// gestion du décalage de fréquence
    	float coef = (float) frequence/(float)frq; 	// >1 si frq est plus grande que frequence perte qualité
    												// <1 si frq est plus petite que frequence retenir la valeur plus longtemps
    												// =1si frequence est égale à frequence
    	int[] tabtemp= new int[(int)(tab.length*coef)];
    	int i=0, j=0;
    	if(coef >1){
    		for(; i<tabtemp.length & j< tab.length;i++){
    			if (i%coef < 1)
    				tabtemp[i]=tab[j];
    			j++;
    		}
    		
    	}else if(coef<1){

    		for(; i<tabtemp.length & j< tab.length;i++){
    			if (i%coef < 0)
    				tabtemp[i]=tabtemp[i-1];
    			else 
    				tabtemp[i]=tab[j];
    			j++;
    		}
    		
    	}else if(coef == 1){
    		for(; i<tabtemp.length ;i++){
    				tabtemp[i]=tab[i];	
    		}
    	}
    	tab=tabtemp.clone();
    	
    	
    	long deb = debut;
    	long fin = debut + tab.length;
    	
    	
    	for (long y=deb ; (y<fin) & (y<echantillons.length) ;y++){
    		echantillons[(int)(y)]=tab[(int)(y-deb)];
    	}
    	nbech=echantillons.length;
    }
    public int[] couper(int numFragment){
    	long deb	= getFragment(numFragment).getDateDebut();
    	long fin 	= getFragment(numFragment).getDateFin();
    	long duree	= getFragment(numFragment).getDuree();
    	int i = 0, j=0;
    	int[] tab = new int[(int) (duree)];
    	int[] temp = echantillons.clone();
    	
    	echantillons = new int [temp.length-tab.length];
    	for(;i< deb;i++){
    		echantillons[j]= temp[i];	
    		j++;
    	}
    	for(i= (int)(fin);i<temp.length;i++){
    		echantillons[j]= temp[i];
    		j++;
    	}
    	removeFragment(numFragment);
    	refresh();
    	return tab;
    }
    
    public void ajoutAuFragment(int[] val, int numeroFragment){
    	refresh();
    	int i=(int) getFragment(numeroFragment).getDateDebut();
    	for(;(i< getFragment(numeroFragment).getDateFin())& (i<val.length+getFragment(numeroFragment).getDateDebut()); i++){
    		echantillons[i]= val[i-(int) getFragment(numeroFragment).getDateDebut()] + echantillons[i];
    	}
    	
    	refresh();
    	
    }
    public void ajoutAuFragment(int val, int numeroFragment){
    	refresh();
    	for (int i = (int)(getFragment(numeroFragment).getDateDebut()) ; 
    			i< getFragment(numeroFragment).getDateFin(); i++){
    		echantillons[i]=echantillons[i] + val;   		
    	}
    	refresh();
    }
    
    public void bourrage(int duree){
    	int[] temp = new int[echantillons.length+duree];
    	int i =0;

    	for(;i< echantillons.length;i++)
    		temp[i]= echantillons[i];	
    	
    	for(;i<echantillons.length+duree ;i++)
    		temp[i]= 0;
    	
    	echantillons=temp.clone();
    	nbech= echantillons.length;

    	
    }

    public String toString(){
   	 refresh();
   	 return (" Nombre d'échantillons du canal: "+getNbech()
   			 +" Nombre de Fragments: "+getNbFragment()+" Frequence: "+frequence);
    }
    
    public boolean equals (Canal c){
    	if (c.echantillons.length!= echantillons.length)
    			return false;
    	for (int i =0; i<echantillons.length;i++)
    		if (c.echantillons[i] != echantillons[i])
    				return false;
    	
    	return true;
    }
}